package com.byx.chatserver.util;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.byx.chatserver.entity.ResultCode;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * FastJsonEnumSerializer
 *
 * @author Superb
 * @date 2021/3/31 23:19
 */
public class FastJsonEnumSerializer implements ObjectSerializer, ObjectDeserializer {
    @Override
    public <T> T deserialze(DefaultJSONParser defaultJSONParser, Type type, Object o) {
        final JSONLexer lexer = defaultJSONParser.lexer;
        final int token = lexer.token();
        Class cls = ((Class) type);
        Object[] enumConstants = cls.getEnumConstants();
        if (ResultCode.class.isAssignableFrom(cls)) {
            for (Object enumConstant : enumConstants) {
                ResultCode baseEnum = (ResultCode) enumConstant;
                Object enumCodeObject = baseEnum.getCode();
                int enumCode = Integer.parseInt(enumCodeObject.toString());
                if (lexer.intValue() == enumCode) {
                    return (T) baseEnum;
                }
            }
        } else {
            //没实现EnumValue接口的 默认的按名字或者按ordinal
            if (token == JSONToken.LITERAL_INT) {
                int intValue = lexer.intValue();
                lexer.nextToken(JSONToken.COMMA);
                if (intValue < 0 || intValue > enumConstants.length) {
                    throw new JSONException(String.format("parse enum %s error, value : %s", cls.getName(), intValue));
                }
                return (T) enumConstants[intValue];
            } else if (token == JSONToken.LITERAL_STRING) {
                return (T) Enum.valueOf(cls, lexer.stringVal());
            }
        }
        return null;
    }

    @Override
    public int getFastMatchToken() {
        return JSONToken.LITERAL_INT;
    }

    @Override
    public void write(JSONSerializer jsonSerializer, Object o, Object o1, Type type, int i) throws IOException {
        SerializeWriter out = jsonSerializer.out;
        if (o instanceof ResultCode) {
            ResultCode resultCode = (ResultCode) o;
            out.write(resultCode.getCode().toString());
        } else {
            out.writeEnum((Enum<?>) o);
        }
    }
}
